// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

#include "stdafx.h"
#include "WorldBuilder.h"
#include "MeshManager.h"
#include "Mesh.h"


MeshManager::MeshManager()
{
}

ref<MeshBuffer> MeshManager::registerMeshBuffer(ref<MeshBuffer> mb)
{
    // If a Mesh by that exists, don't do anything
    if(getMeshBufferByName(mb->getName()) != NULL)
    {
        ASSERT(false);
        return ref<MeshBuffer>();
    }

    for(int i = 0; ; ++i)
    {
        if(m_meshBufferIds.find(i) == m_meshBufferIds.end())
        {
            mb->setId(i);
            m_meshBufferIds.insert(i);
            m_meshBuffers.insert(mb);
            break;
        }
    }

    mb->setManager(this);
    
    ListenerIt it = m_listeners.begin();
    for(; it != m_listeners.end(); ++it)
    {
        MeshListener* listener = *it;
        MeshEvent event_(MeshEvent::MeshBufferAdded);
        event_.manager = this;
        event_.meshBuffer = mb.get(); 
        listener->onMeshEvent(event_);
    }

    return mb;
}

std::wstring MeshManager::generateMeshBufferName(const std::wstring& prefix) const
{
    for(int i = 0; ; ++i) // Will eventually find an unused name
    {
        std::wostringstream oss;
        oss << prefix << i;
        if(getMeshBufferByName(oss.str()) != NULL)
        {
            return oss.str();
        }
    }
}

MeshBuffer* MeshManager::getMeshBufferById(int id) const
{
    // TODO this map should be the other way around for efficiency
    typedef MeshBufferSet::const_iterator It;
    for(It it = m_meshBuffers.begin(); it != m_meshBuffers.end(); ++it)
    {
        if((*it)->getId() == id)
        {
            return it->get();
        }
    }
    return NULL;
}

MeshBuffer* MeshManager::getMeshBufferByName(const std::wstring& name) const
{
    // TODO this map should be the other way around for efficiency
    typedef MeshBufferSet::const_iterator It;
    for(It it = m_meshBuffers.begin(); it != m_meshBuffers.end(); ++it)
    {
        if((*it)->getName() == name)
        {
            return it->get();
        }
    }
    return NULL;
}

// - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

void MeshManager::clear()
{
    m_meshBufferIds.clear();
    m_meshBuffers.clear();
}

// - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

MeshManager::MeshBufferIt MeshManager::beginMeshBuffers() const
{
    return m_meshBuffers.begin();
}

MeshManager::MeshBufferIt MeshManager::endMeshBuffers() const
{
    return m_meshBuffers.end();
}


size_t MeshManager::getMeshBufferCount() const
{
    return m_meshBuffers.size();
}

// - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

void MeshManager::addMeshListener(MeshListener* listener)
{
    ASSERT(m_listeners.find(listener) == m_listeners.end());
    m_listeners.insert(listener);
}

void MeshManager::removeMeshListener(MeshListener* listener)
{
    ASSERT(m_listeners.find(listener) != m_listeners.end());
    m_listeners.erase(listener);
}
    
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
//void MeshManager::notifyMeshAppearanceChanged(MeshEvent& event_)
//{
//    ListenerIt it = m_listeners.begin();
//    for(; it != m_listeners.end(); ++it)
//    {
//        MeshListener* listener = *it;
//        event_.manager = this;
//        listener->onMeshEvent(event_);
//    }
//}
